1 /*
2 * Title: S/MIME Project
3 * Description: S/MIME email sending capabilities
4 * @Author Vladimir Radisic
5 * @Version 2.0.1
6 */
7
8 package org.webdocwf.util.smime.der;
9
10
11 import org.webdocwf.util.smime.exception.SMIMEException;
12 import org.webdocwf.util.smime.exception.ErrorStorage;
13
14
15 /***
16 * Every element of data represented in ASN.1 notation should be encoded
17 * in the process of implementation. It can be done according to BER (Basic
18 * Encoding Rules) or according to DER (Distinguish Encoding Rules). DERObject
19 * class is the root class (super class) of all classes used in DER encodings
20 * of variety elements in data structures used by SMIME.<BR>
21 * <BR>
22 * DER encoding of elements can be performed in two forms: definite form and
23 * indefinite form. DERObject class represents definite form of encoding. Every
24 * encoded element, according to this rules, involves three parts: Identifier
25 * Octet (which represents Tag Type of the encoding data), Length Octets (one
26 * or more octets with the information about number of octets (bytes) in the
27 * content), and Content Octets (they represent data which have to be DER
28 * encoded). <BR>
29 * <BR>
30 * DERObject can be structured or primitive, which depends on his content.
31 */
32 public class DERObject {
33
34 /***
35 * Identifier octet of DER encoding element. It must be in the range 0-255.
36 */
37 private int identifierOctet;
38
39 /***
40 * Length Octets of DER encoding element.
41 */
42 private String lengthOctets = "";
43
44 /***
45 * Content Octets of DER encoding element.
46 */
47 private String contentOctets = "";
48
49 /***
50 * Type of element number (part of Identifier Octet). It must be in the
51 * range 0-30.
52 */
53 private int tagTypeNumber = 0;
54
55 /***
56 * Class Type of element (part of Identifier Octet). It can have values:
57 * 0-Universal, 64-Application, 128-Context, 192-Private (Default 0)
58 */
59 private int tagClassType = 0;
60
61 /***
62 * Complexity type of element. It can have values: 0-Primitive, 32-Structured
63 * (Default 0)
64 */
65 private int tagComplexity = 0;
66
67 /***
68 * Total lenght (number of octets) of DER object (Default 0)
69 */
70 private int totalLength = 0;
71
72 /***
73 * Creates DER Object with defined value for identifier octet.
74 * @param identifierOctet0 must be in the range 0-255 (whithouth 31)
75 * @exception SMIMEException in case of invalid identifierOctet0 parameter
76 */
77 public DERObject(int identifierOctet0) throws SMIMEException {
78 if (identifierOctet0 < 0)
79 throw new SMIMEException(this, 1000);
80 else if (identifierOctet0 > 255)
81 throw new SMIMEException(this, 1001);
82 else if ((identifierOctet0 & 31) == 31)
83 throw new SMIMEException(this, 1002);
84 identifierOctet = identifierOctet0;
85 tagClassType = identifierOctet0 & 192;
86 tagComplexity = identifierOctet0 & 32;
87 tagTypeNumber = identifierOctet0 & 31;
88 totalLength = 1; // Current length of DER object (contain only Identifier octet)
89 }
90
91 /***
92 * Creates DER Object with defined value for identifier octet and values of
93 * content octets
94 * @param identifierOctet0 must be in the range 0-255 (whithouth 31)
95 * @param content0 content of DER Object
96 * @exception SMIMEException in case of invalid identifierOctet0 parameter,
97 * or in case of adding content to DER object of type Null DER object
98 */
99 public DERObject(int identifierOctet0, byte[] content0) throws SMIMEException {
100 this(identifierOctet0);
101 this.addContent(content0);
102 }
103
104 /***
105 * Defines the Lenght Octets which is the part of DEROctet
106 * @param len0 number of octets in the content
107 * @return String representation of Length Octets that correspond to len0 number
108 * @exception SMIMEException caused by non SMIMEException which is:
109 * UnsupportedEncodingException.
110 */
111 private String lengthDERPart(int len0) throws SMIMEException {
112 String returnString = null;
113
114 if (len0 < 128) {
115 byte[] lenByte = new byte[1];
116
117 lenByte[0] = (byte) len0;
118 try {
119 returnString = new String(lenByte, "ISO-8859-1");
120 } catch (Exception e) {
121 throw SMIMEException.getInstance(this, e, "lengthDERPart");
122 }
123 return returnString;
124 } else {
125 int i = 1, a = 1; // i: Number of required bits in length0 number
126
127 for (; (a * 2) <= len0; i++)
128 a = a * 2;
129 i = (int) Math.ceil((double) i / 8); // Number of required bytes for holding length data
130 byte[] lenByte = new byte[i + 1]; // + 1 for first byte in length string
131
132 lenByte[0] = (byte) (i); // First byte define number of following bytes used for holding length data
133 lenByte[0] = (byte) ((int) lenByte[0] | 128); // Indicate complex length octets with bit #8 set to 1
134 for (; i > 0; i--) {
135 a = 255 << ((lenByte.length - i - 1) * 8);
136 lenByte[i] = (byte) ((len0 & a) >> ((lenByte.length - i - 1) * 8));
137 }
138 try {
139 returnString = new String(lenByte, "ISO-8859-1");
140 } catch (Exception e) {
141 throw SMIMEException.getInstance(this, e, "lengthDERPart");
142 }
143 return returnString;
144 }
145 }
146
147 /***
148 * Adds content to DER Object. Used only when the content isn't added earlier
149 * via second type of constructor in DERObject.
150 * @param content0 content octets for adding to DERObject
151 * @exception SMIMEException when adding content to DER object is of type
152 * Null DER object. Also, it can be caused by non SMIMEException which is:
153 * UnsupportedEncodingException.
154 */
155 void addContent(byte[] content0) throws SMIMEException {
156 if (identifierOctet == 5)
157 throw new SMIMEException(this, 1003);
158 try {
159 contentOctets = contentOctets.concat(new String(content0, "ISO-8859-1"));
160 lengthOctets = lengthDERPart(contentOctets.length());
161 totalLength = 1 + contentOctets.length() + lengthOctets.length();
162 } catch (Exception e) {
163 throw SMIMEException.getInstance(this, e, "addContent");
164 }
165 }
166
167 /***
168 * Returns DER encoded object
169 * @return DERObject as byte array
170 * @exception SMIMEException if content of DER object is absent. Also, it can be
171 * caused by non SMIMEException which is: UnsupportedEncodingException.
172 */
173 public byte[] getDEREncoded() throws SMIMEException {
174 if (totalLength == 1 && identifierOctet != 5)
175 throw new SMIMEException(this, 1004);
176 byte[] returnByteArray = null; // Variable for returning DER encoding object represented as byte array
177
178 try {
179 byte[] temp = {
180 (byte) identifierOctet
181 }; // Import identifier octet in DER object string (first byte of string)
182 String derOctet = new String(temp, "ISO-8859-1"); // String with returning DER value
183
184 if (identifierOctet == 5) // Special DER format is for Null DER object
185 {
186 temp[0] = (byte) 0x00;
187 contentOctets = contentOctets.concat(new String(temp, "ISO-8859-1"));
188 derOctet = derOctet.concat(contentOctets);
189 totalLength = 2;
190 returnByteArray = derOctet.getBytes("ISO-8859-1"); // Null DER value
191 } else {
192 derOctet = derOctet.concat(lengthOctets).concat(contentOctets);
193 totalLength = 1 + contentOctets.length() + lengthOctets.length();
194 returnByteArray = derOctet.getBytes("ISO-8859-1");
195 }
196 } catch (Exception e) {
197 throw SMIMEException.getInstance(this, e, "getDEREncoded");
198 }
199 return returnByteArray;
200 }
201
202 /***
203 * Returns Identifier Octet
204 * @return Identifier Octet in the range 0-255
205 */
206 public int getIdentifierOctet() {
207 return identifierOctet;
208 }
209
210 /***
211 * Returns Tag Type
212 * @return Tag Type in the range 0-30
213 */
214 public int getTagTypeNumber() {
215 return tagTypeNumber;
216 }
217
218 /***
219 * Returns Class Type
220 * @return 0-Universal, 64-Application, 128-Context, 192-Private (Default 0)
221 */
222 public int getTagClassType() {
223 return tagClassType;
224 }
225
226 /***
227 * Returns Tag Complexity
228 * @return 0-primitive, 32-structured (Default 0)
229 */
230 public int getTagComplexity() {
231 return tagComplexity;
232 }
233
234 /***
235 * Returns size of content part in DER object (Number of content octets).
236 * @return Number of content octets in DER encoded object
237 */
238 public int getContentPartSize() {
239 return contentOctets.length();
240 }
241
242 /***
243 * Returns size of length part in DER object (Number of length octets).
244 * @return Number of length octets in DER encoded object
245 */
246 public int getLengthPartSize() {
247 return lengthOctets.length();
248 }
249
250 /***
251 * Return content octets part from DER object.
252 * @return Number of content octets in DER encoded object
253 * @exception SMIMEException caused by non SMIMEException which is:
254 * UnsupportedEncodingException .
255 */
256 public byte[] getContentOctets() throws SMIMEException {
257 byte[] returnByteArray = null;
258
259 try {
260 returnByteArray = contentOctets.getBytes("ISO-8859-1");
261 } catch (Exception e) {
262 throw SMIMEException.getInstance(this, e, "getContentOctets");
263 }
264 return returnByteArray;
265 }
266
267 /***
268 * Return length octets part from DER object.
269 * @return Number of length octets in DER encoded object
270 * @exception SMIMEException caused by non SMIMEException which is:
271 * UnsupportedEncodingException.
272 */
273 public byte[] getLengthOctets() throws SMIMEException {
274 byte[] returnByteArray = null;
275
276 try {
277 returnByteArray = lengthOctets.getBytes("ISO-8859-1");
278 } catch (Exception e) {
279 throw SMIMEException.getInstance(this, e, "getLengthOctets");
280 }
281 return returnByteArray;
282 }
283
284 /***
285 * Returns total length of DER object
286 * @return Total length of DER Object (involves identifier octet, length
287 * octets and content octets)
288 */
289 public int getTotalSize() {
290 if (tagTypeNumber == 5)
291 return totalLength + 1;
292 return totalLength;
293 }
294 }
295
This page was automatically generated by Maven